package com.ics.cmsadmin.modules.agent.service.impl;

import com.ics.cmsadmin.frame.core.bean.PageBean;
import com.ics.cmsadmin.frame.core.bean.PageResult;
import com.ics.cmsadmin.frame.core.enums.ApiResultEnum;
import com.ics.cmsadmin.frame.core.exception.CmsException;
import com.ics.cmsadmin.modules.agent.bean.AccountDetailBean;
import com.ics.cmsadmin.modules.agent.bean.AgentAccountBean;
import com.ics.cmsadmin.modules.agent.bean.AgentInfoBean;
import com.ics.cmsadmin.modules.agent.enums.AccountChangesEnum;
import com.ics.cmsadmin.modules.agent.service.AgentAccountService;
import com.ics.cmsadmin.modules.system.emums.SequenceNumberEnum;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;

import static com.ics.cmsadmin.modules.agent.steward.AgentRepositories.accountDetailDao;
import static com.ics.cmsadmin.modules.agent.steward.AgentRepositories.agentAccountDao;
import static com.ics.cmsadmin.modules.agent.steward.AgentServices.agentInfoService;
import static com.ics.cmsadmin.modules.system.steward.SystemServices.sequenceNumberService;

/**
 * a_agent_account
 * Created bylvsw on 2018-37-29 16:09:14.
 */
@Service
public class AgentAccountServiceImpl implements AgentAccountService {

    @Override
    public PageResult<AgentAccountBean> listByLoginUserId(AgentAccountBean bean, String loginUserId, PageBean page) {
        return listByLoginUserId(bean, loginUserId, page, agentAccountDao);
    }

    @Override
    public boolean insert(AgentAccountBean bean) {
        if (bean == null){
            return false;
        }
        if (StringUtils.isBlank(bean.getAgentNo())){
            throw new CmsException(ApiResultEnum.INSERT_TABLE_ITEM_FAIL, "该分销商不存在");
        }
        AgentInfoBean agentInfoBean = agentInfoService.queryById(bean.getAgentNo());
        if (agentInfoBean == null){
            throw new CmsException(ApiResultEnum.INSERT_TABLE_ITEM_FAIL, "该分销商不存在");
        }
        bean.setAccountId(sequenceNumberService.newSequenceNumber(SequenceNumberEnum.AGENT_ACCOUNT));
        return agentAccountDao.insert(bean) == 1;
    }

    @Override
    public AgentAccountBean queryByAgentNo(String agentNo) {
        if (StringUtils.isBlank(agentNo)){
            return null;
        }
        return agentAccountDao.findOne(AgentAccountBean.builder().agentNo(agentNo).build());
    }

    @Override
    public boolean accountChanges(String agentNo, BigDecimal money, AccountChangesEnum accountChangesEnum) {
        if (money == null || accountChangesEnum == null || StringUtils.isBlank(agentNo)){
            throw new CmsException(ApiResultEnum.UPDATE_TABLE_ITEM_FAIL, "账户变动参数有误");
        }
        if ( money.compareTo(new BigDecimal(0)) < 0){
            throw new CmsException(ApiResultEnum.UPDATE_TABLE_ITEM_FAIL, "账户变动金额不能为负数");
        }else if (money.compareTo(new BigDecimal(0)) == 0){
            return true;
        }
        synchronized (agentNo.intern()) {
            AgentInfoBean agentInfoBean = agentInfoService.queryById(agentNo);
            if (agentInfoBean == null){
                throw new CmsException(ApiResultEnum.UPDATE_TABLE_ITEM_FAIL, "不存在该分销商信息");
            }
            AgentAccountBean agentAccountBean = queryByAgentNo(agentNo);
            if (agentAccountBean == null){
                agentAccountBean = AgentAccountBean.builder().agentNo(agentNo).build();
                insert(agentAccountBean);
            }
            switch (accountChangesEnum){
                case PROFIT_INCOME:
                    profitIncome(agentAccountBean, money);
                    break;
                case APPLY_WITHDRAW_CASH:
                    applyWithdrawCash(agentAccountBean, money);
                    break;
                case ACCEPT_WITHDRAW_CASH:
                    acceptWithdrawCash(agentAccountBean, money);
                    break;
                case REFUSE_WITHDRAW_CASH:
                    refuseWithdrawCash(agentAccountBean, money);
                    break;
                case CANCEL_WITHDRAW_CASH:
                    cancelWithdrawCash(agentAccountBean, money);
                    break;
                default:
                    // never go here
                    break;
            }
            AgentAccountBean afterAgentAccountBean = agentAccountDao.queryById(agentAccountBean.getAccountId());
            insertAccoutDetail(afterAgentAccountBean, money, accountChangesEnum);
        }
        return true;
    }

    private void cancelWithdrawCash(AgentAccountBean agentAccountBean, BigDecimal money) {
        if (money.compareTo(agentAccountBean.getFrozenBalance()) > 0){
            throw new CmsException(ApiResultEnum.UPDATE_TABLE_ITEM_FAIL,
                String.format("提现金额%s元不得大于冻结余额%s元", money.toString(), agentAccountBean.getFrozenBalance()));
        }
        agentAccountDao.cancelWithdrawCash(agentAccountBean.getAccountId(), money);
    }

    private void insertAccoutDetail(AgentAccountBean afterAgentAccountBean, BigDecimal money, AccountChangesEnum accountChangesEnum) {
        accountDetailDao.insert(AccountDetailBean.builder()
            .accountId(afterAgentAccountBean.getAccountId())
            .agentNo(afterAgentAccountBean.getAgentNo())
            .money(money)
            .type(accountChangesEnum.name())
            .totalIncome(afterAgentAccountBean.getTotalIncome())
            .withdrawCash(afterAgentAccountBean.getWithdrawCash())
            .balance(afterAgentAccountBean.getBalance())
            .availableBalance(afterAgentAccountBean.getAvailableBalance())
            .frozenBalance(afterAgentAccountBean.getFrozenBalance())
            .build());
    }

    private void refuseWithdrawCash(AgentAccountBean agentAccountBean, BigDecimal money) {
        if (money.compareTo(agentAccountBean.getFrozenBalance()) > 0){
            throw new CmsException(ApiResultEnum.UPDATE_TABLE_ITEM_FAIL,
                String.format("提现金额%s元不得大于冻结余额%s元", money.toString(), agentAccountBean.getFrozenBalance()));
        }
        agentAccountDao.refuseWithdrawCash(agentAccountBean.getAccountId(), money);
    }

    private void acceptWithdrawCash(AgentAccountBean agentAccountBean, BigDecimal money) {
        if (money.compareTo(agentAccountBean.getBalance()) > 0){
            throw new CmsException(ApiResultEnum.UPDATE_TABLE_ITEM_FAIL,
                String.format("提现金额%s元不得大于余额%s元", money.toString(), agentAccountBean.getBalance()));
        }
        if (money.compareTo(agentAccountBean.getFrozenBalance()) > 0){
            throw new CmsException(ApiResultEnum.UPDATE_TABLE_ITEM_FAIL,
                String.format("提现金额%s元不得大于冻结余额%s元", money.toString(), agentAccountBean.getFrozenBalance()));
        }
        agentAccountDao.acceptWithdrawCash(agentAccountBean.getAccountId(), money);
    }

    private void applyWithdrawCash(AgentAccountBean agentAccountBean, BigDecimal money) {
        if (money.compareTo(agentAccountBean.getAvailableBalance()) > 0){
            throw new CmsException(ApiResultEnum.UPDATE_TABLE_ITEM_FAIL,
                String.format("申请提现金额%s元不得大于可用余额%s元", money.toString(), agentAccountBean.getAvailableBalance()));
        }
        agentAccountDao.applyWithdrawCash(agentAccountBean.getAccountId(), money);
    }

    private void profitIncome(AgentAccountBean agentAccountBean, BigDecimal money) {
        agentAccountDao.profitIncome(agentAccountBean.getAccountId(), money);
    }

}
